#ifndef GAME_H
#define GAME_H

#include "Singleton.h"

#include <QDebug>
#include <QList>

class MazeFactory;
class MazeBuilder;

enum Direction { North, South, East, West };

class MapSite {
  public:
    MapSite();
    virtual ~MapSite();
    virtual void Enter() = 0;
    virtual QString type() const = 0;
};


class Room: public MapSite {
public:
    Room(int roomNo);
    ~Room(){}

    MapSite* GetSide(Direction) const;
    void SetSide(Direction, MapSite*);

    virtual void Enter();
    virtual QString type() const;
    virtual int Id() const;

private:
    MapSite* _side[4];
    int _roomNumber;
};

class EnchantedRoom: public Room {
public:
    EnchantedRoom(int roomNo);
    ~EnchantedRoom(){}

    MapSite* GetSide(Direction) const;
    void SetSide(Direction, MapSite*);

    virtual void Enter();
    virtual QString type() const;
    virtual int Id() const;

private:
    MapSite* _side[4];
    int _roomNumber;
};


class Wall: public MapSite {
public:
    Wall(){}
    ~Wall(){}
    virtual void Enter();
    virtual QString type() const;
};


class Door: public MapSite {
public:
    Door(Room* = 0, Room* = 0);
    ~Door(){}

    virtual void Enter();
    virtual QString type() const;
    Room* OtherSideFrom(Room*);

private:
    Room* _room1;
    Room* _room2;
    bool _isOpen;
};

class Maze {    // 迷宫
public:
    Maze();
    ~Maze();

    void AddRoom(Room*);
    Room* RoomNo(int) const;
    int GetRoomSize() const;

private:
    QList<Room*> _rooms;
};

class MazeBuilder {
public:
    virtual void BuildMaze() {}
    virtual void BuildRoom(int room) {}
    virtual void BuildDoor(int roomFrom, int roomTo) {}

    virtual Maze* GetMaze() { return 0; }

protected:
    MazeBuilder(){}
    virtual ~MazeBuilder(){}
};

class StandardMazeBuilder: public MazeBuilder {
public:
    StandardMazeBuilder();
    virtual ~StandardMazeBuilder(){}

    virtual void BuildMaze();
    virtual void BuildRoom(int n);
    virtual void BuildDoor(int roomFrom, int roomTo);

    virtual Maze* GetMaze();

private:
    Direction CommonWall(Room*, Room*);
    Maze* _currentMaze;
};

class MazeGame
{
public:
    MazeGame();
    ~MazeGame();

    Maze* CreateMaze(MazeFactory& factory);
    Maze* CreateMaze(MazeBuilder& builder);
    Maze* CreateMaze();

    virtual Maze* MakeMaze() const
    {
        return new Maze;
    }
    virtual Room* MakeRoom(int n) const
    {
        return new Room(n);
    }
    virtual Door* MakeDoor(Room* r1, Room* r2) const
    {
        return new Door(r1, r2);
    }
    virtual Wall* MakeWall() const
    {
        return new Wall;
    }
};

// 工厂
class EnchantedMazeGame: public MazeGame
{
public:
    EnchantedMazeGame();
    ~EnchantedMazeGame();

    virtual Room* MakeRoom(int n) const
    {
        return new EnchantedRoom(n);
    }
};



// 抽象工厂
class MazeFactory{
public:
    MazeFactory();
    virtual ~MazeFactory();
    virtual Maze* MakeMaze() const
    { return new Maze; }
    virtual Wall* MakeWall() const
    { return new Wall; }
    virtual Room* MakeRoom(int n) const
    { return new Room(n); }
    virtual Door* MakeDoor(Room* r1, Room* r2) const
    { return new Door(r1, r2); }
};

// 魔法迷宫
class EnchantedMazeFactory: public MazeFactory {
public:
    EnchantedMazeFactory();
    ~EnchantedMazeFactory();
    virtual Maze* MakeMaze() const
    { return new Maze; }
    virtual Wall* MakeWall() const
    { return new Wall; }
    virtual Room* MakeRoom(int n) const
    { return new EnchantedRoom(n); }
    virtual Door* MakeDoor(Room* r1, Room* r2) const
    { return new Door(r1, r2); }
};

#endif // GAME_H
